package com.oig.sys.workflow.schedule;

import com.oig.sys.workflow.vo.CronJobVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.annotation.Scope;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
import org.springframework.scheduling.support.CronTrigger;
import org.springframework.stereotype.Component;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Future;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;


/**
 * 这就是个单例bean，默认就是单例的，这里显示配置一下
 * 这个服务只能单副本, 简单做一下，大部分任务可以在系统内调度，方便管理
 * 如果有大量任务或者复杂的，可以用dolphinScheduler或conductor
 */
@Component
@Scope(value = ConfigurableBeanFactory.SCOPE_SINGLETON)
@Slf4j
public class CronJobManager {


    private final Map<Integer, ScheduledFuture<?>> scheduledFutureMap = new ConcurrentHashMap<>() ;
    private final ThreadPoolTaskScheduler threadPoolTaskScheduler;
    private final CronJobHandler cronJobHandler;

    public CronJobManager(ThreadPoolTaskScheduler threadPoolTaskScheduler,
                          CronJobHandler cronJobHandler){
        this.threadPoolTaskScheduler = threadPoolTaskScheduler;
        this.cronJobHandler = cronJobHandler;
    }


    public void startJob(CronJobVo cronJob){
        if (scheduledFutureMap.containsKey(cronJob.getId())){
            log.debug("job is already started, {}",cronJob);
            return;
        }
        ScheduledFuture<?> scheduledFuture = threadPoolTaskScheduler.schedule(()->cronJobHandler.execute(cronJob), new CronTrigger(cronJob.getScheduleCron()));
        scheduledFutureMap.put(cronJob.getId(),scheduledFuture) ;
        log.debug("start job..{}",cronJob);
    }

    public void stopJob(Integer jobId){
        if (scheduledFutureMap.containsKey(jobId)){
            ScheduledFuture<?> scheduledFuture = scheduledFutureMap.get(jobId) ;
            scheduledFuture.cancel(true);
            scheduledFutureMap.remove(jobId);
            log.debug("remove job...{}",jobId);
        } else {
            log.debug("no job..{}",jobId);
        }
    }

    public boolean executeJob(CronJobVo cronJob){
        log.info("execute job ...{}", cronJob);
        Future<?> future = threadPoolTaskScheduler.submit(()->cronJobHandler.execute(cronJob) );
        try{
            Object o = future.get(1, TimeUnit.MINUTES);
            return (Boolean)o;
        } catch (Exception e){
            log.error("future get result error..", e);
        }
        return false;
    }

}
